#include "../include/head.h"
#include "../include/list.h"

// 创建一个带头的双链表
p_list create_list()
{
    p_list head = (p_list)malloc(sizeof(list_t));
    if (head == NULL)
    {
        printf("malloc failed!\n");
        return NULL;
    }
    memset(head, 0, sizeof(user_data));
    head->next = NULL;
    return head;
}

// 计算文件中的课程数量
int coursecount()
{
    FILE *fp = fopen(STUDENTS_FILE, "r");
    char buffer[1024];
    int tabCount = 0; // 制表符计数初始化为0
    if (fgets(buffer, sizeof(buffer), fp))
    { // 尝试读取第一行
        for (int i = 0; buffer[i] != '\0'; ++i)
        { // 遍历每一字符
            if (buffer[i] == '\t')
            {               // 如果是'\t'
                tabCount++; // 增加计数
            }
        }
    }
    int count;
    count = tabCount - 6;
    count = count - count / 2;
    return count;
}

// 插入数据到链表(尾插)
int insert_list(p_list head, user_data data)
{
    if (head == NULL)
    {
        printf("list is error\n");
        return -1;
    }
    p_list newnode = (p_list)malloc(sizeof(list_t));
    if (newnode == NULL)
    {
        printf("malloc failed\n");
        return -1;
    }
    newnode->data = data;
    newnode->next = newnode->pre = NULL;

    p_list phead = head;
    while (phead->next != NULL)
    {
        phead = phead->next;
    }
    // 此时phead指向尾结点
    newnode->pre = phead;
    phead->next = newnode;
    return 0;
}

// 学生选课(公选课)
void choose_course(p_list head)
{
    if (head == NULL)
    {
        return;
    }
    system("clear");

    char classname[20][20];
    int num = 0;          // 课程位置
    int i;                // 循环遍历
    int flag = initcount; // 记住课程数量
    int favorate = 1;     // 循环退出标志
    p_list q = tlist->next;
    int print_num = 1, classname_num = 0;

    printf("你可以选择如下课程\n");
    while (q != NULL)
    {
        if (strcmp(q->data.class, "数学分析") != 0 && strcmp(q->data.class, "数据结构") != 0)
        {
            printf("%d、%s\n", print_num, q->data.class); // 遍历输出可选课程
            print_num++;
        }
        strcpy(classname[classname_num], q->data.class); // 课程名写入到classname[20][20]
        classname_num++;
        q = q->next;
    }

    printf("%s同学,请选择您要加入的课程:", head->data.name);

    // 找新课程插入位置
    for (i = 0; i < initcount; i++)
    {
        if (strcmp(head->data.course[i].coursename, "NULL") == 0)
        {
            num = i;     // 记录课程位置
            initcount--; // 因为不论课程数量变没变,外面都++了,所以要--
            break;
        }
    }
    if (i >= initcount) // 没有找到空位置
    {
        num = initcount;
    }

    while (favorate) // 选课
    {
        int option = 0;
        scanf("%d", &option);
        if (option < print_num) // 若输入选择错误则退出
        {
            if (if_full(option) == 0 && reacourse(head, option, flag) == 0) // 课程人数未满且为选修过
            {
                strcpy(head->data.course[num].coursename, classname[option + 1]);
                head->data.course[num].score = 0;
                favorate = 0;
            }
            else
            {
                if (if_full(option) != 0)
                {
                    printf("该课程人数已满,请重新选择:");
                }
                else
                {
                    printf("你已选修该课程,请重新选择:");
                }
                favorate = 1;
                continue;
            }
        }
        else
        {
            initcount--;
            break;
        }
    }
}

// 判断课程人数是否已满  超过:1   未超过:0
int if_full(int i)
{
    course_situation(slist); // 选课情况
    if (choosecount[i + 1].count >= MAX_COUNT)
    {
        return 1;
    }
    return 0;
}

// 判断是否有重复课程  重复:1    未重复:0
int reacourse(p_list head, int option, int flag)
{
    for (size_t i = 0; i < flag; i++)
    {
        if (strcmp(head->data.course[i].coursename, choosecount[option + 1].coursename) == 0)
        {
            return 1;
        }
    }
    return 0;
}

// 将链表更新到文件
int list_update_file(p_list list, char *file)
{
    // 打开文件
    FILE *fp = fopen(file, "w+");
    if (fp == NULL)
    {
        printf("文件打开失败\n");
        return -1;
    }
    p_list phead = list->next;
    while (phead != NULL)
    {
        fprintf(fp, "%s\t%s\t%s\t%s\t%d\t%s",
                phead->data.name, phead->data.id,
                phead->data.sex, phead->data.class,
                phead->data.age, phead->data.password);
        if (list == slist) // 若为学生表则还有课程要更新
        {
            int i = 0;
            while (i < initcount)
            {
                fprintf(fp, "\t%s\t%d", phead->data.course[i].coursename, phead->data.course[i].score);
                i++;
            }
            fprintf(fp, "\n");
        }
        else
        {
            fprintf(fp, "\n");
        }
        phead = phead->next;
    }
    // 关闭文件
    fclose(fp);
    return 0;
}

// 将文件更新到链表
int file_update_list(p_list list, char *file)
{
    FILE *fp = fopen(file, "r+");
    if (fp == NULL)
    {
        printf("文件打开失败\n");
        return -1;
    }
    user_data newnode;
    while (fscanf(fp, "%s\t%s\t%s\t%s\t%d\t%s", newnode.name, newnode.id,
                  newnode.sex, newnode.class, &newnode.age, newnode.password) != EOF)
    {
        if (list == slist) // 若为学生表则还有课程要更新
        {
            int i = 0;
            while (i < initcount)
            {
                if (fscanf(fp, "\t%s\t%d", newnode.course[i].coursename, &newnode.course[i].score) != EOF)
                {
                    i++;
                }
            }
        }
        insert_list(list, newnode); // 插入结点到链表
    }
    fclose(fp);
    return 0;
}

// 录入学生成绩:任课老师录入所授课程成绩
int print_scorse(p_list list, p_list p)
{
    if (list == NULL)
    {
        return -1;
    }
    p_list phead = list->next;
    while (phead != NULL)
    {
        for (size_t i = 0; i < initcount; i++)
        {
            if (strcmp(p->data.class, phead->data.course[i].coursename) == 0 && phead->data.course[i].score == 0)
            {
                printf("%s\t%s的\t%s成绩为:", phead->data.id, phead->data.name, phead->data.course[i].coursename);
                scanf("%d", &phead->data.course[i].score);
                list_update_file(slist, STUDENTS_FILE);
            }
        }
        phead = phead->next;
    }
    return 0;
}

// 查询数据：用id账号查
p_list find_list(p_list list, char *id)
{
    if (list == NULL)
    {
        printf("list is error\n");
        return NULL;
    }
    p_list phead = list->next;
    while (phead != NULL)
    {
        if ((!strcmp(phead->data.id, id)))
        {
            return phead;
        }
        phead = phead->next;
    }
    if (phead == NULL)
    {
        return NULL;
    }
}

// 修改密码
int change_password(p_list list, char *id)
{
    if (list == NULL)
    {
        printf("list is error\n");
        return -1;
    }
    p_list phead = find_list(list, id);

    if (phead != NULL)
    {
        printf("密码修改为:");
        scanf("%s", phead->data.password);
        printf("修改成功\n");
    }
    else
    {
        printf("没有这个人\n");
    }
    return 0;
}

// 删除信息(删除指定结点)
int del_list(p_list list)
{
    if (list == NULL)
    {
        printf("list is error\n");
        return -1;
    }
    char id[20];

    printf("请输入要删除的账号:");
    scanf("%s", id);

    p_list phead = find_list(list, id);
    if (phead != NULL)
    {
        if (phead->next == NULL)
        {
            phead->pre->next = NULL;
            return 0;
        }
        else
        {
            phead->next->pre = phead->pre;
            phead->pre->next = phead->next;
        }

        // 释放结点
        memset(phead, 0, sizeof(user_data));
        free(phead);
    }
    else
    {
        printf("没有这个人\n");
    }

    return 0;
}

// 老师修改
int teacher_change_list(p_list list)
{
    if (list == NULL)
    {
        printf("list is error\n");
        return -1;
    }
    char id[20];
    printf("请输入要修改学生的账号:");
    scanf("%s", id);
    p_list phead = find_list(list, id);
    if (phead != NULL)
    {
        int option = 0;
        while (1)
        {
            printf("请做出如下选择:\n");
            printf("1、修改姓名\n");
            printf("2、修改学号\n");
            printf("3、修改性别\n");
            printf("4、修改班级\n");
            printf("5、修改年龄\n");
            printf("6、修改密码\n");
            printf("7、退出\n");
            printf("请做出你的选择:");
            scanf("%d", &option);
            switch (option)
            {
            case 1:
            {
                /* 修改姓名 */
                printf("姓名 %s修改为:", phead->data.name);
                scanf("%s", phead->data.name);
                break;
            }
            case 2:
            {
                /* 修改学号 */
                printf("学号 %s修改为:", phead->data.id);
                scanf("%s", phead->data.id);
                break;
            }
            case 3:
            {
                /* 修改性别 */
                printf("性别 %s修改为:", phead->data.sex);
                scanf("%s", phead->data.sex);
                break;
            }
            case 4:
            {
                /* 修改班级 */
                printf("班级 %s修改为:", phead->data.class);
                scanf("%s", phead->data.class);
                break;
            }
            case 5:
            {
                /* 修改年龄 */
                printf("年龄 %d修改为:", phead->data.age);
                scanf("%d", &phead->data.age);
                break;
            }
            case 6:
            {
                /* 修改密码 */
                printf("密码 %s修改为:", phead->data.password);
                scanf("%s", phead->data.password);
                break;
            }
            case 7:
                /* 退出 */
                return 0;
                break;
            default:
                break;
            }
        }
    }
    else
    {
        printf("没有这个学生\n");
    }

    return 0;
}

// 按成绩排序
int sort_scorce(p_list list)
{
    sort_class(list); // 按班级排序
    // 将总分置零
    p_list ph = slist->next;
    while (ph != NULL)
    {
        ph->data.sum = 0;
        ph = ph->next;
    }
    // 求总分
    ph = slist->next;
    while (ph != NULL)
    {
        for (size_t i = 0; i < initcount; i++)
        {
            ph->data.sum += ph->data.course[i].score;
        }
        ph = ph->next;
    }

    // 按成绩分班排序
    p_list phead = list->next;
    while (phead != NULL)
    {

        p_list flag = phead;
        while (flag != NULL)
        {
            if (flag->next != NULL && strcmp(flag->data.class, flag->next->data.class) == 0) // 同班
            {
                flag = flag->next;
            }
            else
            {
                break;
            }
        }
        p_list p = phead;
        user_data temp;
        while (p != flag) // 分班排序
        {
            p_list q = phead;
            while (q != flag)
            {
                if (q->data.sum < q->next->data.sum)
                {
                    temp = q->data;
                    q->data = q->next->data;
                    q->next->data = temp;
                }
                q = q->next;
            }
            p = p->next;
        }
        phead = p->next;
    }

    show_scorse(list); // 输出排好序的成绩

    return 0;
}
// 按班级排序
int sort_class(p_list list)
{
    if (list == NULL)
    {
        printf("list is error\n");
        return -1;
    }

    // 按班级排序
    user_data temp;
    p_list phead = list->next;
    while (phead->next != NULL)
    {
        p_list qhead = list->next;
        while (qhead->next != NULL)
        {
            if (strcmp(qhead->data.class, qhead->next->data.class) > 0)
            {
                temp = qhead->data;
                qhead->data = qhead->next->data;
                qhead->next->data = temp;
            }
            qhead = qhead->next;
        }
        phead = phead->next;
    }
}

// 按学号排序
int sort_id(p_list list)
{
    if (list == NULL)
    {
        printf("list is error\n");
        return -1;
    }

    user_data temp;
    p_list phead = list->next;
    while (phead->next != NULL)
    {
        p_list qhead = list->next;
        while (qhead->next != NULL)
        {
            if (strcmp(qhead->data.id, qhead->next->data.id) > 0)
            {
                temp = qhead->data;
                qhead->data = qhead->next->data;
                qhead->next->data = temp;
            }
            qhead = qhead->next;
        }
        phead = phead->next;
    }
    show_list(list);
}

// 输出排好序的学生成绩
int show_scorse(p_list list)
{
    p_list k = list->next;
    int rank = 1;
    while (k != NULL)
    {
        printf("第 %d 名:", rank);
        printf("%s\t%s\t%s\t", k->data.name, k->data.class, k->data.id);
        for (size_t i = 0; i < initcount; i++)
        {
            printf("%s\t%d\t", k->data.course[i].coursename, k->data.course[i].score);
        }
        if (k->next != NULL && (strcmp(k->data.class, k->next->data.class)) == 0) // 同班
        {
            rank++;
        }
        else // 不同班,名次重新从1开始
        {
            rank = 1;
        }
        printf("总分\t%d\n", k->data.sum);
        k = k->next;
    }
    return 0;
}

// 选课情况
int course_situation(p_list list)
{
    if (list == NULL)
    {
        return -1;
    }

    p_list q = tlist->next;
    int n = 0;
    while (q != NULL)
    {
        strcpy(choosecount[n].coursename, q->data.class);
        choosecount[n].count = 0;
        n++;
        q = q->next;
    }
    course_num = n;
    p_list phead = list->next;

    // 遍历求每门课程被选情况
    while (phead != NULL) // 遍历学生
    {
        for (size_t i = 0; i < initcount; i++) // 遍历学生的每一门课程
        {
            for (size_t j = 0; j < course_num; j++) // 所有课程名
            {
                if (strcmp(phead->data.course[i].coursename, choosecount[j].coursename) == 0)
                {
                    choosecount[j].count++;
                }
            }
        }
        phead = phead->next;
    }

    return 0;
}

// 将选课情况写入文件
int course_file(p_list list)
{
    course_situation(slist);
    char class[2][10] = {"必修", "选修"};
    int i = 0;
    FILE *fp = fopen(CLASS_FILE, "w+");
    p_list p;
    if (fp == NULL)
    {
        printf("文件打开失败\n");
        return -1;
    }
    fprintf(fp, "----------------------------------------选课情况表-------------------------------------\n\n");
    for (i = 0; i < course_num; i++)
    {
        p = tlist->next;
        fprintf(fp, "课程名:%s\t\t", choosecount[i].coursename);
        while (p != NULL)
        {
            if (strcmp(p->data.class, choosecount[i].coursename) == 0)
            {
                fprintf(fp, "授课教师:%s\t\t", p->data.name);
            }

            p = p->next;
        }
        if (i < 2)
        {
            fprintf(fp, "课程性质:%s\t\t\n", class[0]);
        }
        else
        {
            fprintf(fp, "课程性质:%s\t\t最多可选:%d\t\t已选人数:%d\t\t还可再选:%d\n", class[1], MAX_COUNT, choosecount[i].count, MAX_COUNT - choosecount[i].count);
        }
    }
    fclose(fp);
    return 0;
}

// 老师查看所授课程的被选情况
int student_choose(p_list p)
{
    if (p == NULL)
    {
        return 0;
    }
    p_list phead = slist->next;
    printf("课程名:%s     授课老师:%s\t\n所选学生:\n", p->data.class, p->data.name);
    while (phead != NULL)
    {
        for (size_t i = 0; i < initcount; i++)
        {
            if (strcmp(p->data.class, phead->data.course[i].coursename) == 0)
            {
                printf("%s\t%s\t%s\n", phead->data.id, phead->data.name, phead->data.class);
            }
        }
        phead = phead->next;
    }
    printf("\n");
    return 0;
}

// 遍历整个信息表
int show_list(p_list head)
{
    if (head == NULL)
    {
        printf("list is error\n");
        return -1;
    }
    p_list phead = head->next;
    while (phead != NULL)
    {
        printf("%s\t%s\t%s\t%s\t%d\t%s",
               phead->data.name, phead->data.id,
               phead->data.sex, phead->data.class,
               phead->data.age, phead->data.password);
        if (head == slist)
        {
            for (size_t i = 0; i < initcount; i++)
            {
                printf("\t%s\t%d", phead->data.course[i].coursename, phead->data.course[i].score);
            }
        }
        printf("\n");
        phead = phead->next;
    }
    return 0;
}
